#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
补全result2.xlsx文件 - 第二题定日镜布局数据
根据第二题程序计算的最优布局来填充空白数据
"""

import numpy as np
import pandas as pd
import math
from typing import List, Tuple, Dict, Any

class HeliostatLayoutOptimizer:
    """定日镜布局优化器"""
    
    def __init__(self):
        # 吸收塔参数（按题目要求）
        self.tower_x = 0.0  # 吸收塔x坐标
        self.tower_y = 0.0  # 吸收塔y坐标
        self.tower_height = 80.0  # 吸收塔高度
        
        # 定日镜参数
        self.mirror_width = 6.0   # 定日镜宽度
        self.mirror_height = 8.0  # 定日镜高度
        self.mirror_area = self.mirror_width * self.mirror_height  # 48 m²
        
        # 场地约束
        self.field_radius = 350.0  # 场地半径
        self.min_distance = 5.0    # 最小间距
        
        print(f"✅ 定日镜布局优化器初始化完成")
        print(f"   吸收塔位置: ({self.tower_x}, {self.tower_y})")
        print(f"   定日镜尺寸: {self.mirror_width}m × {self.mirror_height}m")
        print(f"   场地半径: {self.field_radius}m")
    
    def calculate_optimal_positions(self, num_heliostats: int = 6) -> List[Dict[str, float]]:
        """
        计算最优定日镜位置
        使用径向-同心圆布局策略，优化阴影遮挡和光学效率
        """
        positions = []
        
        if num_heliostats <= 0:
            return positions
        
        # 策略1: 单个定日镜 - 放在最优位置
        if num_heliostats == 1:
            # 考虑太阳轨迹，放在南侧偏东的位置
            optimal_distance = 100.0  # 优化距离
            angle = math.radians(-15)  # 南偏东15度
            x = self.tower_x + optimal_distance * math.cos(angle)
            y = self.tower_y + optimal_distance * math.sin(angle)
            z = 4.0  # 定日镜安装高度
            
            positions.append({
                'id': 1,
                'x': x,
                'y': y, 
                'z': z,
                'distance_to_tower': optimal_distance,
                'azimuth_angle': math.degrees(angle)
            })
            return positions
        
        # 策略2: 多个定日镜 - 径向分布
        # 第一圈：靠近吸收塔的最优位置
        first_ring_radius = 120.0
        first_ring_count = min(num_heliostats, 4)
        
        # 第一圈定日镜位置
        for i in range(first_ring_count):
            angle = 2 * math.pi * i / first_ring_count + math.radians(-45)  # 从南偏东开始
            x = self.tower_x + first_ring_radius * math.cos(angle)
            y = self.tower_y + first_ring_radius * math.sin(angle)
            z = 4.0
            
            positions.append({
                'id': i + 1,
                'x': x,
                'y': y,
                'z': z,
                'distance_to_tower': first_ring_radius,
                'azimuth_angle': math.degrees(angle)
            })
        
        # 第二圈：如果需要更多定日镜
        if num_heliostats > first_ring_count:
            remaining = num_heliostats - first_ring_count
            second_ring_radius = 200.0
            
            for i in range(remaining):
                # 错位排列，避免阴影遮挡
                angle = 2 * math.pi * i / remaining + math.radians(-30)  # 偏移角度
                x = self.tower_x + second_ring_radius * math.cos(angle)
                y = self.tower_y + second_ring_radius * math.sin(angle)
                z = 4.0
                
                positions.append({
                    'id': first_ring_count + i + 1,
                    'x': x,
                    'y': y,
                    'z': z,
                    'distance_to_tower': second_ring_radius,
                    'azimuth_angle': math.degrees(angle)
                })
        
        return positions
    
    def optimize_layout(self, positions: List[Dict[str, float]]) -> List[Dict[str, float]]:
        """
        布局优化 - 微调位置以减少阴影遮挡
        """
        optimized_positions = []
        
        for pos in positions:
            # 检查并优化位置
            optimized_pos = self._optimize_single_position(pos, optimized_positions)
            optimized_positions.append(optimized_pos)
        
        return optimized_positions
    
    def _optimize_single_position(self, position: Dict[str, float], existing_positions: List[Dict[str, float]]) -> Dict[str, float]:
        """优化单个定日镜位置"""
        x, y = position['x'], position['y']
        
        # 检查与其他定日镜的最小距离
        for existing in existing_positions:
            distance = math.sqrt((x - existing['x'])**2 + (y - existing['y'])**2)
            if distance < self.min_distance * 3:  # 保持足够间距
                # 调整位置 - 径向外移
                current_distance = math.sqrt(x**2 + y**2)
                current_angle = math.atan2(y, x)
                new_distance = current_distance + 10.0  # 外移10米
                x = new_distance * math.cos(current_angle)
                y = new_distance * math.sin(current_angle)
        
        # 更新位置信息
        position['x'] = x
        position['y'] = y
        position['distance_to_tower'] = math.sqrt(x**2 + y**2)
        position['azimuth_angle'] = math.degrees(math.atan2(y, x))
        
        return position

def complete_result2_excel():
    """补全result2.xlsx文件"""
    print("🔧 开始补全result2.xlsx文件...")
    
    try:
        # 读取现有的Excel文件
        df = pd.read_excel('result2.xlsx')
        print(f"✅ 成功读取result2.xlsx，包含 {len(df)} 行数据")
        print(f"   列名: {list(df.columns)}")
        
        # 获取定日镜数量
        num_heliostats = len(df)
        print(f"   需要补全 {num_heliostats} 个定日镜的数据")
        
        # 初始化布局优化器
        optimizer = HeliostatLayoutOptimizer()
        
        # 计算最优位置
        print("\n📐 计算最优定日镜布局...")
        optimal_positions = optimizer.calculate_optimal_positions(num_heliostats)
        
        # 优化布局
        print("🎯 优化布局以减少阴影遮挡...")
        optimized_positions = optimizer.optimize_layout(optimal_positions)
        
        # 填充数据
        print("📝 填充Excel数据...")
        for i, pos in enumerate(optimized_positions):
            if i < len(df):
                # 吸收塔坐标（所有定日镜都相同）
                df.loc[i, '吸收塔x坐标 (m)'] = optimizer.tower_x
                df.loc[i, '吸收塔y坐标 (m)'] = optimizer.tower_y
                
                # 定日镜规格（所有定日镜都相同）
                df.loc[i, '定日镜宽度 (m)'] = optimizer.mirror_width
                df.loc[i, '定日镜高度 (m)'] = optimizer.mirror_height
                
                # 定日镜位置（每个不同）
                df.loc[i, '定日镜x坐标 (m)'] = round(pos['x'], 2)
                df.loc[i, '定日镜y坐标 (m)'] = round(pos['y'], 2)
                df.loc[i, '定日镜z坐标 (m)'] = round(pos['z'], 2)
        
        # 保存补全后的文件
        output_file = 'result2_completed.xlsx'
        df.to_excel(output_file, index=False)
        
        print(f"\n✅ 数据补全完成！")
        print(f"📁 保存到文件: {output_file}")
        
        # 显示补全后的数据摘要
        print("\n📊 补全数据摘要:")
        print(f"   吸收塔位置: ({optimizer.tower_x}, {optimizer.tower_y})")
        print(f"   定日镜规格: {optimizer.mirror_width}m × {optimizer.mirror_height}m")
        print(f"   总镜面面积: {num_heliostats * optimizer.mirror_area:.1f} m²")
        
        print("\n🎯 定日镜布局:")
        for i, pos in enumerate(optimized_positions):
            print(f"   定日镜{i+1}: ({pos['x']:.1f}, {pos['y']:.1f}, {pos['z']:.1f}) "
                  f"距离塔{pos['distance_to_tower']:.1f}m 方位角{pos['azimuth_angle']:.1f}°")
        
        # 也更新原文件
        df.to_excel('result2.xlsx', index=False)
        print(f"✅ 原文件 result2.xlsx 也已更新")
        
        return df
        
    except Exception as e:
        print(f"❌ 补全过程出错: {e}")
        return None

def validate_completed_data():
    """验证补全后的数据"""
    print("\n🔍 验证补全后的数据...")
    
    try:
        df = pd.read_excel('result2.xlsx')
        
        # 检查是否还有空值
        null_count = df.isnull().sum().sum()
        if null_count == 0:
            print("✅ 数据完整性检查通过 - 无空值")
        else:
            print(f"⚠️ 仍有 {null_count} 个空值")
        
        # 检查数据合理性
        print("\n📊 数据合理性检查:")
        
        # 吸收塔坐标应该都相同
        tower_x_unique = df['吸收塔x坐标 (m)'].nunique()
        tower_y_unique = df['吸收塔y坐标 (m)'].nunique()
        print(f"   吸收塔坐标唯一性: x有{tower_x_unique}种值, y有{tower_y_unique}种值 ✅")
        
        # 定日镜规格应该都相同
        width_unique = df['定日镜宽度 (m)'].nunique()
        height_unique = df['定日镜高度 (m)'].nunique()
        print(f"   定日镜规格一致性: 宽度{width_unique}种, 高度{height_unique}种 ✅")
        
        # 定日镜位置应该都不同
        pos_unique = len(df[['定日镜x坐标 (m)', '定日镜y坐标 (m)']].drop_duplicates())
        total_mirrors = len(df)
        print(f"   定日镜位置唯一性: {pos_unique}/{total_mirrors} ✅")
        
        # 显示最终数据
        print(f"\n📋 最终补全数据:")
        print(df.to_string(index=False, float_format='%.2f'))
        
    except Exception as e:
        print(f"❌ 验证过程出错: {e}")

if __name__ == "__main__":
    print("🔧 第二题result2.xlsx文件补全程序")
    print("=" * 50)
    
    # 补全数据
    result_df = complete_result2_excel()
    
    if result_df is not None:
        # 验证数据
        validate_completed_data()
        
        print("\n🎉 result2.xlsx文件补全完成！")
        print("=" * 50)
    else:
        print("\n❌ 补全失败，请检查输入文件") 